package com.cbs.android.module.discussion.activity;

import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.text.Html;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.cbs.android.component.application.activity.CBSActivity;
import com.cbs.android.component.application.activity.CBSDialogFragment;
import com.cbs.android.component.application.activity.delayedtask.DelayedTask;
import com.cbs.android.component.application.activity.handler.CBSSimpleActivityResultHandler;
import com.cbs.android.component.applicationutils.Global;
import com.cbs.android.component.log.L;
import com.cbs.android.component.network.HttpClient;
import com.cbs.android.component.network.Request;
import com.cbs.android.component.network.SimpleResponseHandler;
import com.cbs.android.component.network.decoder.GsonDecoder;
import com.cbs.android.component.toast.Toast;
import com.cbs.android.extension.glide.target.RoundedImageViewTarget;
import com.cbs.android.extension.glide.urlloader.qiniu.QiniuUrlLoader;
import com.cbs.android.extension.glide.urlloader.qiniu.url.AvatarUrl;
import com.cbs.android.function.input.ButtonDialogFragment;
import com.cbs.android.module.discussion.DiscussionModule;
import com.cbs.android.module.discussion.R;
import com.cbs.android.module.discussion.entity.Comment;
import com.cbs.android.module.discussion.entity.Reply;
import com.cbs.android.module.discussion.entity.ReplySnapshot;
import com.cbs.android.module.discussion.entity.Star;
import com.cbs.android.module.discussion.entity.StarSnapshot;
import com.cbs.android.module.discussion.entity.SubjectSnapshot;
import com.cbs.android.module.discussion.entity.UnStarSnapshot;
import com.cbs.android.module.discussion.utils.Constants;
import com.cbs.android.module.discussion.utils.DiscussionActivityType;
import com.cbs.android.module.discussion.utils.SimpleJsonCombiner;
import com.cbs.android.module.user.network.CBSUserRequest;
import com.cbs.android.module.user.user.UserModule;
import com.cbs.android.module.user.user.entity.User;
import com.cbs.android.module.userkit.UserKit;
import com.google.gson.Gson;

import java.util.Arrays;

import cn.bingoogolapple.refreshlayout.BGANormalRefreshViewHolder;
import cn.bingoogolapple.refreshlayout.BGARefreshLayout;
import okhttp3.FormBody;
import okhttp3.RequestBody;

/**
 * Created by broche on 9/24/15.
 */
public abstract class DiscussionDetailActivity<Subject> extends CBSActivity implements View.OnClickListener {
    private static final String TAG = DiscussionDetailActivity.class.getName();
    private static final String CommentUrlTpl = "social/api/v1/forums/%d/subjects/%d/comments/%d";
    private static final String ReportUrlTpl = "social/api/v1/forums/%d/subjects/%d/comments/%d/reports";
    private static final String StarUrlTpl = "social/api/v1/forums/%d/subjects/%d/comments/%d/stars";
    private static final String UnStarUrlTpl = "social/api/v1/forums/%d/subjects/%d/comments/%d/stars/%d";

    protected abstract int getForumId();

    protected abstract Subject onGetData(Context context, int subjectId);

    protected abstract SubjectSnapshot onSnapshot(Context context, Subject subject);

    protected abstract void onUserClick(Context context, int senderId);

    protected Class<? extends ReplyAddActivity> getReplyAddActivityClass() {
        return ReplyAddActivity.class;
    }

    private HttpClient httpClient = Global.getHttpClient().clone();
    private RefreshFinishTask refreshFinishTask = new RefreshFinishTask();


    private int subjectId = -1;
    private int commentId = -1;
    private Comment comment = null;
    private Subject subjectObject = null;

    private BGARefreshLayout refreshView = null;
    private LinearLayout senderView = null;
    private ImageView senderAvatarView = null;
    private TextView senderNicknameView = null;
    private ImageView senderSexView = null;
    private TextView timestampView = null;
    private LinearLayout starContainerView = null;
    private ImageView starView = null;
    private TextView starCountView = null;
    private TextView contentView = null;
    private LinearLayout repliesView = null;
    private View repliesEmptyView = null;

    private ContentClickListener contentClickListener = new ContentClickListener();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        boolean showInput = getIntent().getBooleanExtra(Constants.ShowInput, false);
        subjectId = getIntent().getIntExtra(Constants.SubjectId, -1);
        commentId = getIntent().getIntExtra(Constants.CommentId, -1);

        if (subjectId < 0) {
            Toast.show(getString(R.string.cbs_discussion_hint_paramerror));
            finish();
            return;
        }
        if (commentId < 0) {
            Toast.show(getString(R.string.cbs_discussion_hint_paramerror));
            finish();
            return;
        }
        httpClient.setDebug(DiscussionModule.isDebug());
        setContentView(R.layout.cbs_discussion_detail);

        refreshView = (BGARefreshLayout) findViewById(R.id.cbs_discussion_detail_refresh);
        senderView = (LinearLayout) findViewById(R.id.cbs_discussion_detail_sender);
        senderAvatarView = (ImageView) findViewById(R.id.cbs_discussion_detail_senderavatar);
        senderNicknameView = (TextView) findViewById(R.id.cbs_discussion_detail_sendernickname);
        senderSexView = (ImageView) findViewById(R.id.cbs_discussion_detail_sendersex);
        timestampView = (TextView) findViewById(R.id.cbs_discussion_detail_timestamp);
        starContainerView = (LinearLayout) findViewById(R.id.cbs_discussion_detail_starcontainer);
        starView = (ImageView) findViewById(R.id.cbs_discussion_detail_star);
        starCountView = (TextView) findViewById(R.id.cbs_discussion_detail_starcount);
        contentView = (TextView) findViewById(R.id.cbs_discussion_detail_content);
        repliesView = (LinearLayout) findViewById(R.id.cbs_discussion_detail_replies);
        repliesEmptyView = findViewById(R.id.cbs_discussion_detail_replies_empty);

        findViewById(R.id.cbs_discussion_detail_back).setOnClickListener(this);
        senderView.setOnClickListener(this);
        starContainerView.setOnClickListener(this);
        contentView.setOnClickListener(contentClickListener);

        refreshView.setDelegate(new MyDelegate());
        refreshView.setRefreshViewHolder(new BGANormalRefreshViewHolder(this, true));
        refreshView.beginRefreshing();

        if (showInput) {
            doDelayed(new DelayedTask() {
                @Override
                public void doDelayed(Bundle data) {
                    Intent intent = new Intent(DiscussionDetailActivity.this, getReplyAddActivityClass());
                    intent.putExtra(Constants.ForumId, getForumId());
                    intent.putExtra(Constants.SubjectId, subjectId);
                    intent.putExtra(Constants.CommentId, commentId);
                    intent.putExtra(Constants.ConsigneeId, getIntent().getIntExtra(Constants.ConsigneeId, -1));
                    intent.putExtra(Constants.SubjectSnapshot, getIntent().getStringExtra(Constants.SubjectSnapshot));
                    intent.putExtra(Constants.ReplySnapshot, getIntent().getStringExtra(Constants.ReplySnapshot));
                    startActivityForResult(intent, 0, R.anim.cbs_slide_in_bottom, 0);
                }
            }, 500);
        }
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.cbs_discussion_detail_back) {
            finish();
        } else if (v.getId() == R.id.cbs_discussion_detail_sender) {
            if (comment != null) {
                onUserClick(DiscussionDetailActivity.this, comment.getSenderId());
            }
        } else if (v.getId() == R.id.cbs_discussion_detail_starcontainer) {
            if (comment == null) {
                return;
            }
            if (UserModule.getUser() == null) {
                UserKit.login(DiscussionDetailActivity.this, new CBSSimpleActivityResultHandler() {
                    @Override
                    public void onSuccess(int requestCode, Intent data) {
                        Toast.show(getString(R.string.cbs_discussion_hint_loginsuccess));
                    }

                    @Override
                    public void onCancel(int requestCode, Intent data) {
                        Toast.show(getString(R.string.cbs_discussion_hint_logincanceled));
                    }
                });
                return;
            }
            if (subjectObject == null) {
                Toast.show(getString(R.string.cbs_discussion_hint_dataloading));
                return;
            }
            SubjectSnapshot subjectSnapshot = onSnapshot(DiscussionDetailActivity.this, subjectObject);
            Star star = null;
            for (Star tstar : comment.getStars()) {
                if (tstar.getUserId() == UserModule.getUser().getId()) {
                    star = tstar;
                    break;
                }
            }
            User user = UserModule.getUser();
            Gson gson = new Gson();
            if (star != null) {
                UnStarSnapshot unstarSnapshot = new UnStarSnapshot()
                        .setCommentid(comment.getId()).setSubjectid(subjectId)
                        .setSenderid(user.getId()).setSendernickname(user.getNickName())
                        .setSenderavatar(user.getAvatar()).setSendersex(user.getSex())
                        .setConsigneeid(comment.getSenderId()).setConsigneenickname(comment.getSenderNickName())
                        .setConsigneeavatar(comment.getSenderAvatar()).setConsigneesex(comment.getSenderSex())
                        .setRefcontent(comment.getContent());
                String unstarSnapshotStr = gson.toJson(unstarSnapshot);
                String subjectSnapshotStr = gson.toJson(subjectSnapshot);
                String snapshot = SimpleJsonCombiner.combineObject(unstarSnapshotStr, subjectSnapshotStr);
                RequestBody requestBody = new FormBody.Builder()
                        .add("type", getForumId() + "_" + DiscussionActivityType.UnStar)
                        .add("consigneeid", comment.getSenderId() + "")
                        .add("snapshot", snapshot)
                        .build();
                Request request = new CBSUserRequest(String.format(Global.getServerHost() + "/" + UnStarUrlTpl, getForumId(), subjectId, comment.getId(), star.getId()))
                        .delete(requestBody)
                        .setResponseHandler(new SimpleResponseHandler() {
                            @Override
                            public void onSuccess(Object entity) {
                                for (Star tstar : comment.getStars()) {
                                    if (tstar.getUserId() == UserModule.getUser().getId()) {
                                        comment.getStars().remove(tstar);
                                        int starCount = comment.getStarCount();
                                        starCount--;
                                        starCount = starCount < 0 ? 0 : starCount;
                                        comment.setStarCount(starCount);
                                        break;
                                    }
                                }
                                notifyChanged();
                                Toast.show(getString(R.string.cbs_discussion_hint_unstarsuccess));
                            }

                            @Override
                            public void onFailure(int code, String message) {
                                L.e(TAG, String.format("code: %d\tmessage: %s", code, message));
                                Toast.show(getString(R.string.cbs_discussion_hint_unstarfailure));
                            }
                        });
                httpClient.send(request);
            } else {
                StarSnapshot starSnapshot = new StarSnapshot()
                        .setCommentid(comment.getId()).setSubjectid(subjectId)
                        .setSenderid(user.getId()).setSendernickname(user.getNickName())
                        .setSenderavatar(user.getAvatar()).setSendersex(user.getSex())
                        .setConsigneeid(comment.getSenderId()).setConsigneenickname(comment.getSenderNickName())
                        .setConsigneeavatar(comment.getSenderAvatar()).setConsigneesex(comment.getSenderSex())
                        .setRefcontent(comment.getContent());
                String starSnapshotStr = gson.toJson(starSnapshot);
                String subjectSnapshotStr = gson.toJson(subjectSnapshot);
                String snapshot = SimpleJsonCombiner.combineObject(starSnapshotStr, subjectSnapshotStr);
                RequestBody requestBody = new FormBody.Builder()
                        .add("type", getForumId() + "_" + DiscussionActivityType.Star)
                        .add("consigneeid", comment.getSenderId() + "")
                        .add("snapshot", snapshot)
                        .build();
                Request request = new CBSUserRequest(String.format(Global.getServerHost() + "/" + StarUrlTpl, getForumId(), subjectId, comment.getId()))
                        .setDecoder(new GsonDecoder(Star.class))
                        .post(requestBody)
                        .setResponseHandler(new SimpleResponseHandler<Star>() {
                            @Override
                            public void onSuccess(Star entity) {
                                comment.getStars().add(entity);
                                comment.setStarCount(comment.getStarCount() + 1);
                                notifyChanged();
                                Toast.show(getString(R.string.cbs_discussion_hint_starsuccess));
                            }

                            @Override
                            public void onFailure(int code, String message) {
                                L.e(TAG, String.format("code: %d\tmessage: %s", code, message));
                                Toast.show(getString(R.string.cbs_discussion_hint_starfailure));
                            }
                        });
                httpClient.send(request);
            }
        }
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 0) {
            if (resultCode == RESULT_OK) {
                refreshView.beginRefreshing();
            }
        }
    }

    private void notifyChanged() {
        if (comment == null) {
            return;
        }

        int userid = -1;
        if (UserModule.getUser() == null) {
            userid = UserModule.getUser().getId();
        }

        Glide.with(this)
                .using(new QiniuUrlLoader(this))
                .load(new AvatarUrl(DiscussionModule.getAvatarPath(comment.getSenderAvatar())))
                .asBitmap()
                .placeholder(R.drawable.cbs_discussion_avatar)
                .error(R.drawable.cbs_discussion_avatar)
                .into(new RoundedImageViewTarget(senderAvatarView));
        senderNicknameView.setText(comment.getSenderNickName());
        senderSexView.setImageResource(comment.getSenderSex() == 0 ? R.drawable.cbs_discussion_sex_female_default : R.drawable.cbs_discussion_sex_male_default);
        timestampView.setText(DiscussionModule.getDateFormatter().format(comment.getTimestamp()));
        starView.setImageResource(R.drawable.cbs_discussion_star_unstared_default);
        for (Star star : comment.getStars()) {
            if (star.getUserId() == userid) {
                starView.setImageResource(R.drawable.cbs_discussion_star_stared_default);
                break;
            }
        }
        starCountView.setText(comment.getStarCount() + "");
        contentView.setText(comment.getContent());

        repliesView.removeAllViews();
        for (Reply reply : comment.getReplies()) {
            View view = getLayoutInflater().inflate(R.layout.cbs_discussion_list_item_reply, repliesView, false);
            TextView replyContentView = (TextView) view.findViewById(R.id.cbs_discussion_list_item_reply_content);
            String content;
            int blue;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                blue = getColor(R.color.cbs_discussion_reply_blue);
            } else {
                blue = getResources().getColor(R.color.cbs_discussion_reply_blue);
            }
            int darkgrey;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                darkgrey = getColor(R.color.cbs_discussion_reply_darkgrey);
            } else {
                darkgrey = getResources().getColor(R.color.cbs_discussion_reply_darkgrey);
            }
            int grey;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                grey = getColor(R.color.cbs_discussion_reply_grey);
            } else {
                grey = getResources().getColor(R.color.cbs_discussion_reply_grey);
            }
            int size1 = (int) getResources().getDimension(R.dimen.cbs_discussion_reply_content_sender);
            int size2 = (int) getResources().getDimension(R.dimen.cbs_discussion_reply_content);
            if (reply.getConsigneeId() == -1) {
                content = String.format(getResources().getString(R.string.cbs_discussion_reply_content_1), blue, size1, reply.getSenderNickName(), darkgrey, size1, reply.getContent(), grey, size2, DiscussionModule.getDateFormatter().format(reply.getTimestamp()));
            } else {
                content = String.format(getResources().getString(R.string.cbs_discussion_reply_content_2), blue, size1, reply.getSenderNickName(), darkgrey, size1, blue, size1, reply.getConsigneeNickName(), darkgrey, size1, reply.getContent(), grey, size2, DiscussionModule.getDateFormatter().format(reply.getTimestamp()));
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                replyContentView.setText(Html.fromHtml(content, Html.FROM_HTML_MODE_COMPACT));
            } else {
                replyContentView.setText(Html.fromHtml(content));
            }
            view.setOnClickListener(DiscussionDetailActivity.this);
            view.setTag(reply);
            repliesView.addView(view);
        }
        if (comment.getReplies().size() <= 0) {
            repliesView.setVisibility(View.GONE);
            repliesEmptyView.setVisibility(View.VISIBLE);
        } else {
            repliesView.setVisibility(View.VISIBLE);
            repliesEmptyView.setVisibility(View.GONE);
        }
    }

    private void onRefreshFinish(int action) {
        Bundle bundle = new Bundle();
        bundle.putInt("action", action);
        doDelayed(refreshFinishTask, bundle);
    }

    private class RefreshFinishTask implements DelayedTask {
        private int refreshCounter = 0;

        @Override
        public void doDelayed(Bundle data) {
            int action = data.getInt("action");

            if (action == 0) {
                refreshCounter = 0;
            } else {
                refreshCounter++;
                if (refreshCounter >= 2) {
                    refreshView.endRefreshing();
                }
            }
        }
    }

    private class ContentClickListener implements View.OnClickListener {
        @Override
        public void onClick(View view) {
            if (UserModule.getUser() == null) {
                UserKit.login(DiscussionDetailActivity.this, new CBSSimpleActivityResultHandler() {
                    @Override
                    public void onSuccess(int requestCode, Intent data) {
                        Toast.show("登陆成功");
                    }

                    @Override
                    public void onCancel(int requestCode, Intent data) {
                        Toast.show("取消登录");
                    }
                });
                return;
            }

            ButtonDialogFragment fragment = new ButtonDialogFragment()
                    .setItems(Arrays.asList(getResources().getStringArray(R.array.cbs_discussion_buttons)))
                    .setOnButtonListener(new ButtonDialogFragment.OnButtonListener() {
                        @Override
                        public void onButtonClick(CBSDialogFragment cbsDialogFragment, int index, String s) {
                            if (index == 0) {
                                reply();
                            } else if (index == 1) {
                                report();
                            } else {
                                cancel();
                            }
                        }
                    });
            fragment.show(getSupportFragmentManager(), "dialog");
        }

        private void reply() {
            if (subjectObject == null) {
                Toast.show(getString(R.string.cbs_discussion_hint_dataloading));
                return;
            }
            SubjectSnapshot subjectSnapshot = onSnapshot(DiscussionDetailActivity.this, subjectObject);
            User user = UserModule.getUser();
            ReplySnapshot replySnapshot = new ReplySnapshot()
                    .setSubjectid(subjectId).setCommentid(commentId)
                    .setSenderid(user.getId()).setSendernickname(user.getNickName()).setSenderavatar(user.getAvatar()).setSendersex(user.getSex())
                    .setConsigneeid(-1).setConsigneenickname("").setConsigneeavatar("").setConsigneesex(1)
                    .setLastconsigneeid(-1).setLastconsigneenickname("").setLastconsigneeavatar("").setLastconsigneesex(1)
                    .setObserverid(comment.getSenderId()).setObservernickname(comment.getSenderNickName()).setObserveravatar(comment.getSenderAvatar()).setObserversex(comment.getSenderSex())
                    .setRefcontent("").setCtxcontent(comment.getContent());
            Gson gson = new Gson();
            String replySnapshotStr = gson.toJson(replySnapshot);
            String subjectSnapshotStr = gson.toJson(subjectSnapshot);

            Intent intent = new Intent(DiscussionDetailActivity.this, getReplyAddActivityClass());
            intent.putExtra(Constants.ForumId, getForumId());
            intent.putExtra(Constants.SubjectId, subjectId);
            intent.putExtra(Constants.CommentId, commentId);
            intent.putExtra(Constants.ConsigneeId, -1);
            intent.putExtra(Constants.SubjectSnapshot, subjectSnapshotStr);
            intent.putExtra(Constants.ReplySnapshot, replySnapshotStr);
            startActivityForResult(intent, 0, R.anim.cbs_slide_in_bottom, 0);
        }

        private void report() {
            RequestBody requestBody = new FormBody.Builder()
                    .build();
            Request request = new CBSUserRequest(String.format(Global.getServerHost() + "/" + ReportUrlTpl, getForumId(), subjectId, commentId))
                    .post(requestBody)
                    .setResponseHandler(new SimpleResponseHandler() {
                        @Override
                        public void onSuccess(Object entity) {
                            Toast.show(getString(R.string.cbs_discussion_hint_reportsuccess));
                        }

                        @Override
                        public void onFailure(int code, String message) {
                            L.e(TAG, String.format("code: %d\tmessage: %s", code, message));
                            Toast.show(getString(R.string.cbs_discussion_hint_reportfailure));
                        }
                    });
            httpClient.send(request);
        }

        private void cancel() {
            // NO ACTION
        }
    }

    private class MyDelegate implements BGARefreshLayout.BGARefreshLayoutDelegate {
        @Override
        public void onBGARefreshLayoutBeginRefreshing(BGARefreshLayout bgaRefreshLayout) {
            onRefreshFinish(0);
            Request request = new CBSUserRequest(String.format(Global.getServerHost() + "/" + CommentUrlTpl, getForumId(), subjectId, commentId))
                    .setDecoder(new GsonDecoder(Comment.class))
                    .setResponseHandler(new SimpleResponseHandler<Comment>() {
                        @Override
                        public void onSuccess(Comment entity) {
                            comment = entity;
                            notifyChanged();
                            onRefreshFinish(1);
                        }

                        @Override
                        public void onFailure(int code, String message) {
                            Toast.show(getString(R.string.cbs_discussion_hint_loadfailure));
                            onRefreshFinish(1);
                        }

                        @Override
                        public void onException(Request request, Exception e) {
                            super.onException(request, e);
                            onRefreshFinish(1);
                        }
                    });
            httpClient.send(request);

            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    subjectObject = onGetData(DiscussionDetailActivity.this, subjectId);
                    onRefreshFinish(1);
                }
            });
            thread.start();
        }

        @Override
        public boolean onBGARefreshLayoutBeginLoadingMore(BGARefreshLayout bgaRefreshLayout) {
            // TODO load more
            return false;
        }
    }

    protected void setTitle(String title) {
        TextView titleView = (TextView) findViewById(R.id.cbs_discussion_detail_title);
        titleView.setText(title);
    }
}
